package com.example.demo.configuration.security;

import com.example.demo.entity.security.*;
import com.example.demo.service.user.impl.MyAuthenticationProvider;
import com.example.demo.service.user.impl.UserServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.annotation.Resource;

/**
 * @description:
 * @author: cj
 * @create: 09-02-08 09:28:49
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    /**
     * 登录成功的返回 JSON 格式的数据给前端（否则为 html）
     */
    @Resource
    private LoginSuccessHandler loginSuccessHandler;
    /**
     * 登录失败 JSON 格式的数据给前端（否则为 html）
     */
    @Resource
    private LoginFailureHandler loginFailureHandler;
    /**
     * 未登录 JSON 格式的数据给前端（否则为 html）
     */
    @Resource
    private LoginEntryPoint loginEntryPoint;
    /**
     * 权限不足 JSON 格式的数据给前端（否则为 html）
     */
    @Resource
    private RoleAccessDeniedHandler roleAccessDeniedHandler;
    @Resource
    private Md5PasswordEncoder passwordEncoder;
    @Resource
    private UserServiceImpl userService;

    @Resource(name = "myAuthenticationProvider")
    private MyAuthenticationProvider authenticationProvider;

    /**
     * 自定义密码校验
     *
     * @return Md5PasswordEncoder
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new Md5PasswordEncoder();
    }


    @Override
    public void configure(HttpSecurity http) throws Exception {


        http

//                .authenticationProvider( authenticationProvider() )
                .authorizeRequests()
//                .antMatchers( "/user/accountRegister" ).permitAll()
                .antMatchers( "/**" ).permitAll()
                // .antMatchers("/admin1/**").hasRole("USER")
                //尚未匹配的任何URL都要求用户进行身份验证
                .anyRequest().authenticated()
                .and()
                //使用自带的登录
                .formLogin()
                .usernameParameter( "name" )
                .loginProcessingUrl( "/user/accountLogin" )
                .permitAll()
                //登录失败，返回json
                .failureHandler( loginFailureHandler )
                //登录成功，返回json
                .successHandler( loginSuccessHandler )
                .and()
                .httpBasic()
                //未登录时，进行json格式的提示，很喜欢这种写法，不用单独写一个又一个的类
                .authenticationEntryPoint( loginEntryPoint )
                .and()
                .exceptionHandling()
                //没有权限，返回json
                .accessDeniedHandler( roleAccessDeniedHandler )
                //开启跨域访问 开启模拟请求，比如API POST测试工具的测试，不开启时，API POST为报403错误
                .and()
                .csrf().disable();
        ;


    }


    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        //对默认的UserDetailsService进行覆盖
        authenticationProvider.setUserDetailsService( userService );
        authenticationProvider.setPasswordEncoder( passwordEncoder );
        return authenticationProvider;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        MyAuthenticationProvider authenticationProvider = new MyAuthenticationProvider();
        //这里可启用我们自己的登陆验证逻辑
        auth.authenticationProvider( authenticationProvider );
    }
}
